import json
import matplotlib.pyplot as plt
from PIL import Image
from matplotlib.patches import Rectangle

# 读取坐标文件
def read_coordinates(file_path):
    with open(file_path, 'r') as file:
        coordinates = json.load(file)
    return coordinates

# 在图片上绘制点和矩形框，并确保所有内容都可见
def plot_points_and_rects_on_image(image_path, coordinates, rects, output_path=None, padding=50):
    # 打开图片
    image = Image.open(image_path)
    image_width, image_height = image.size

    # 提取x和y坐标（无需翻转y坐标，因为sharp的坐标系原点在左上角）
    x_coords = [point['x'] for point in coordinates]
    y_coords = [point['y'] for point in coordinates]  # 无需翻转 y 坐标

    # 提取矩形的x, y, width, height（无需翻转y坐标）
    rects_x = [rect['x'] for rect in rects]
    rects_y = [rect['y'] for rect in rects]  # 无需翻转矩形 y 坐标
    rects_width = [rect['width'] for rect in rects]
    rects_height = [rect['height'] for rect in rects]

    # 计算矩形的边界（左下角和右上角）
    rects_min_x = [rect['x'] for rect in rects]
    rects_max_x = [rect['x'] + rect['width'] for rect in rects]
    rects_min_y = [rect['y'] for rect in rects]  # 使用原始 y 坐标
    rects_max_y = [rect['y'] + rect['height'] for rect in rects]

    # 计算所有点和矩形的最小和最大坐标
    all_x = x_coords + rects_min_x + rects_max_x
    all_y = y_coords + rects_min_y + rects_max_y
    min_x, max_x = min(all_x), max(all_x)
    min_y, max_y = min(all_y), max(all_y)

    # 计算画布需要扩展的范围（包括padding）
    canvas_min_x = min(min_x, 0) - padding
    canvas_max_x = max(max_x, image_width) + padding
    canvas_min_y = min(min_y, 0) - padding
    canvas_max_y = max(max_y, image_height) + padding

    # 创建一个空白画布
    fig, ax = plt.subplots(figsize=((canvas_max_x - canvas_min_x) / 100, (canvas_max_y - canvas_min_y) / 100))

    # 设置画布的范围（包括padding）
    ax.set_xlim(canvas_min_x, canvas_max_x)
    ax.set_ylim(canvas_min_y, canvas_max_y)  # 无需翻转 y 轴

    # 显示图片（将图片放置在正确的位置）
    ax.imshow(image, extent=[0, image_width, 0, image_height])  # 无需翻转 y 轴

    # 绘制坐标点
    ax.scatter(x_coords, y_coords, color='red', marker='o', s=50)  # s 是点的大小

    # 在每个点附近添加 idx 和 idy 信息
    for point in coordinates:
        x, y = point['x'], point['y']  # 使用原始 y 坐标
        idx, idy = point['idx'], point['idy']
        label = f"({idx}, {idy})"  # 标签文本
        ax.text(
            x, y + 40,  # 文本位置（点下方 40 像素）
            label,      # 文本内容
            fontsize=18, # 字体大小
            color='green',  # 文本颜色
            ha='center'     # 水平对齐方式
        )

    # 绘制矩形框
    for rect in rects:
        rect_patch = Rectangle(
            (rect['x'], rect['y']),  # 矩形的左上角坐标（无需翻转 y 坐标）
            rect['width'],           # 矩形的宽度
            rect['height'],          # 矩形的高度
            linewidth=2,             # 边框宽度
            edgecolor='blue',        # 边框颜色
            facecolor='none'         # 无填充颜色
        )
        ax.add_patch(rect_patch)

    # 隐藏坐标轴
    ax.axis('off')

    # 保存或显示图像
    if output_path:
        plt.savefig(output_path, bbox_inches='tight', pad_inches=0)
        print(f"图像已保存到: {output_path}")
    else:
        plt.show()

# 示例调用
if __name__ == "__main__":
    # 图片路径
    image_path = "map_20250123_095144122.png"  # 替换为你的图片路径
    # 坐标文件路径
    coordinates_path = "points.json"  # 替换为你的坐标文件路径
    # 矩形文件路径
    rects_path = "rects.json"  # 替换为你的矩形文件路径
    # 输出图片路径（可选）
    output_path = "output_image.jpg"  # 如果需要保存绘制后的图片，指定路径

    # 读取坐标
    coordinates = read_coordinates(coordinates_path)
    # 读取矩形
    rects = read_coordinates(rects_path)

    # 在图片上绘制点和矩形框
    plot_points_and_rects_on_image(image_path, coordinates, rects, output_path, padding=50)